#include "ramka.hpp"
//#include "Wyjatki.hpp"
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <boost/crc.hpp>  // for boost::crc_32_type
#include <vector>



using namespace std;

Ramka::Ramka() {

}

int Ramka::pobierzTemat() const {
   return temat;
}

string Ramka::pobierzDane() const {
   return dane;
}

string Ramka::pobierzLogin() const {
   if(temat == logowanieTCP) {
      return login;
   } else {
      //throw
   }
}

string Ramka::pobierzHaslo() const {
   if(temat == logowanieTCP) {
      return haslo;
   } else {
      //throw
   }

}

int Ramka::pobierzOdKogo() const {
   return odKogo;
}

void Ramka::ustawOdKogo(int odKogo) {
   this->odKogo = odKogo;
}


void Ramka::sprawdzRamkeOdebrana(string ramka) {
   size_t pos;
   boost::crc_32_type  tempCRC;
   string stringCRC;
   string test = ramka;
   
   if ( ((pos = ramka.find_first_of(">")) != string::npos) && (pos == 0) ) {
      ramka.erase(ramka.begin());
   } else {
      //throw Wyjatek("Bledna ramka (brakuje >)");
   }


   if ( ((pos = ramka.find_first_of("<")) != string::npos) && (pos == ramka.size() - 1) ) {
      ramka.erase(ramka.begin() + pos);
   } else {
      //throw Wyjatek("Bledna ramka (brakuje <)");
   }

    
   // szukam rozpoczecia CRC w ramce i je wycinam

   if ( (pos  = ramka.rfind("/")) != string::npos ) {
      stringCRC = ramka.substr(pos + 1);
      ramka.erase(pos);
      if ( !(stringCRC.size()) ) {
	 //throw Wyjatek("Bledna ramka (brak CRC)");
      }
   }
   else {
      //throw Wyjatek("Bledna ramka (brakuje drugiego /)");
   }

   tempCRC.process_block(ramka.c_str(), ramka.c_str() + ramka.size());

   // sprawdzam CRC pobrane i policzone
   if ( tempCRC.checksum() != boost::lexical_cast<boost::uint32_t>(stringCRC)) {
      //throw Wyjatek("Bledna ramka (niezgodne CRC)");
   }


   // wycinam temat wiadomosci i dane wiadomosci (jesli jakies sa)
   if ( (pos  = ramka.find("/")) != string::npos ) {
      temat = boost::lexical_cast<int>(ramka.substr(0, pos));
      dane = ramka.substr(pos + 1);
   }
   else {
      //throw Wyjatek("Bledna ramka (brakuje pierwszego |)");
   }


   if(temat == logowanieTCP) {
      login = pobierzLoginZDanych();
      haslo = pobierzHasloZDanych();
   }
}

/*static*/
string Ramka::stworzRamkeDoWyslania(int temat,
				    string wiadomosc) {
   
   boost::crc_32_type CRC;
   string wynik(boost::lexical_cast<string>(temat) + "/" + wiadomosc);
   //wynik.append("/");
   //wynik.append(wiadomosc);
   CRC.process_block(wynik.c_str(), wynik.c_str() + wynik.size());
   wynik = ">" + wynik + "/" + boost::lexical_cast<string>(CRC.checksum()) + "<";
   //string wynikCRC(">" + wynik + "/" + boost::lexical_cast<string>(CRC.checksum()) + "<");
   
   return wynik;
}

/*static*/
string Ramka::zamienMapeCLINaString(cliext::map<System::String^,int> mapa) {
   string wynik;
   cliext::map<System::String^,int>::const_iterator it = mapa.begin();
   
   for(; it != mapa.end(); ++it) {
	  const int second = it->second;
      wynik.append(Ramka::ToStdString(it->first) + ":" +
		   boost::lexical_cast<string>(second) + ";");
   }
   return wynik;
}

std::vector<std::string> Ramka::podzielNaRamki(std::string dane) {
	std::vector<std::string> wynik;
	size_t found;
	while(true) {
		if( (found = dane.find("<")) != string::npos ) {
			wynik.push_back(dane.substr(0, found));
			dane.erase(0, found + 1);
	    } else {
			break;
		}
	}
	return wynik;

}

/*static*/
string Ramka::zamienWektorCLINaString(cliext::vector<System::String^> wektor) {
   string wynik;
   cliext::vector<System::String^>::const_iterator it = wektor.begin();
   
   for(; it != wektor.end(); ++it) {
      wynik.append(Ramka::ToStdString(*it) + ";");
   }
   return wynik;
}


/*static*/
cliext::map<System::String^,int> Ramka::zamienStringNaMapeCLI(string dane) {
	size_t found;
    string first;
	int second;
    //map<string,string> wynik;
	cliext::map<System::String^,int> wynik;
    while(dane.size()) {
        if( (found = dane.find(":")) != string::npos ) {
	   first = dane.substr(0, found);
	   dane.erase(0, found + 1);
        } else {

        }
        if( (found = dane.find(";")) != string::npos ) {
	   second = boost::lexical_cast<int>(dane.substr(0, found));
	   dane.erase(0, found + 1);
        } else {

        }
        wynik[Ramka::ToSysString(first)] = second;
    }
    return wynik;  
   /*cliext::map<System::String^,int> wynik;
   System::String^ daneSys = Ramka::ToSysString(dane);
   int found;
   System::String^ first;
   int second;
   while(!System::String::IsNullOrEmpty(daneSys)) {
      if((found = daneSys->IndexOf(":")) > 0) {

	 first = daneSys->Substring(0, found);
	 daneSys = daneSys->Substring(found + 1);
      } else {

      }
      if((found = daneSys->IndexOf(";")) > 0) {	 
	 // parse integer
	 second = System::Int32::Parse(daneSys->Substring(0, found));
	 daneSys = daneSys->Substring(found + 1);
      } else {
	   
      }

      wynik[first] = second;
   }
   return wynik;   */
}

string Ramka::zamienMapeNaString(map<string,string> mapa) {
   string wynik;
   map<string,string>::const_iterator it = mapa.begin();   
   for(; it != mapa.end(); ++it) {
      wynik.append(it->first + ":" + it->second + ";");
   }
   return wynik;
}

cliext::map<System::String^,System::String^> Ramka::zamienStringNaMape(string dane) {
    size_t found;
    string first, second;
    cliext::map<System::String^,System::String^> wynik;

    while(dane.size()) {
        if( (found = dane.find(":")) != string::npos ) {
	   first = dane.substr(0, found);
	   dane.erase(0, found + 1);
        } else {

        }
        if( (found = dane.find(";")) != string::npos ) {
	   second = dane.substr(0, found);
	   dane.erase(0, found + 1);
        } else {

        }
        wynik[Ramka::ToSysString(first)] = Ramka::ToSysString(second);
    }
    return wynik;  
}

cliext::vector<System::String^> Ramka::zamienStringNaWektorCLI(string dane) {
	cliext::vector<System::String^> wynik;
   size_t found;  
    while(dane.size()) {
   
        if( (found = dane.find(";")) != string::npos ) {
			wynik.push_back(Ramka::ToSysString(dane.substr(0, found)));
            dane.erase(0, found + 1);            
        } else {
            //throw MException(__FILE__, "Brak \"@\" ", __LINE__);
        }        
    }
   return wynik; 
   /*cliext::vector<System::String^> wynik;
   System::String^ daneSys = Ramka::ToSysString(dane);
   int found;
   System::String^ first;
   int second;
   while(!System::String::IsNullOrEmpty(daneSys)) {
      if((found = daneSys->IndexOf(";")) > 0) {

	 first = daneSys->Substring(0, found);
	 daneSys = daneSys->Substring(found + 1);
      } else {

      }
      wynik.push_back(first);
   }
   return wynik; */
}

string Ramka::zamienWektorDoubleNaString(cliext::vector<double> wektor) {
   string wynik;
   cliext::vector<double>::const_iterator it = wektor.begin();
   
   for(; it != wektor.end(); ++it) {
      //wynik.append(boost::lexical_cast<std::string>(*it) + ";");
   }
   return wynik;
}

cliext::vector<double> Ramka::zamienStringNaWektorDouble(string dane) {
   cliext::vector<double> wynik;
   size_t found;  
    while(dane.size()) {
   
        if( (found = dane.find(";")) != string::npos ) {
			wynik.push_back(boost::lexical_cast<double>(dane.substr(0, found)));
            dane.erase(0, found + 1);            
        } else {
            //throw MException(__FILE__, "Brak \"@\" ", __LINE__);
        }        
    }
   return wynik; 
}

int Ramka::enumToInt(TematKomunikacji temat) {
   switch (temat) {
   case logowanieTCP:
      return 0;
      break;
   case wylogowanieTCP:
      return 1;
      break;
   case NowyKrokSymulacjiTCP:
      return 2;
   break;
   case zmianaObiektuTCP:
      return 3;
      break;
   case zmianaRegulatoraTCP:
      return 4;
      break;
   case zmianaWartosciZadanejTCP:
      return 5;
      break;
   case nowaMapaObiektowTCP:
      return 6;
      break;
   case nowaMapaRegulatorowTCP:
      return 7;
      break;
   case nowaMapaWartZadTCP:
      return 8;
      break;
   case nowaListaUstawionychGeneratorowTCP:
      return 9;
      break;
   case czyscRegulatorTCP:
      return 10;
      break;
   case czyscObiektTCP:
      return 11;
      break;
   case resetSymulacjiTCP:
      return 12;
	 break;   
   }
}

TematKomunikacji Ramka::intToEnum(int wartosc) {
   switch (wartosc) {

   case 0:
      return logowanieTCP;
      break;

   case 1:
      return wylogowanieTCP;
      break;

   case 2:
      return NowyKrokSymulacjiTCP;
      break;

   case 3:
      return zmianaObiektuTCP;
      break;

   case 4:
      return zmianaRegulatoraTCP;
      break;

   case 5:
      return zmianaWartosciZadanejTCP;
      break;

   case 6:
      return nowaMapaObiektowTCP;
      break;

   case 7:
      return nowaMapaRegulatorowTCP;
      break;

   case 8:
      return nowaMapaWartZadTCP;
      break;

   case 9:
      return nowaListaUstawionychGeneratorowTCP;
      break;
   
   case 10:
      return czyscRegulatorTCP;
      break;

   case 11:
      return czyscObiektTCP;
      break;

   case 12:
      return resetSymulacjiTCP;
      break;   
   }
}

string Ramka::pobierzLoginZDanych() {
   size_t found;
   if( (found = dane.find("#")) != string::npos) {
      return dane.substr(0, found);
   } else {
      //throw Wyjatek("Brak znaku #, wiec nie moge znalezc loginu");
   }
}

string Ramka::pobierzHasloZDanych() {
   size_t found;
   if( (found = dane.find("#")) != string::npos) {
      return dane.substr(found + 1, string::npos);
   } else {
      //throw Wyjatek("Brak znaku #, wiec nie moge znalezc hasla");
   }
}



Ramka::~Ramka() {

}
